/*
 * Copyright 2012 Marsrutai.lt
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *   http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package lt.marsrutai.mobile.android.util;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

/**
 * Builds sqlite WHERE query
 * 
 * @author Justas
 */
public class SQLiteWhereQueryBuilder {
    
    private String query = StringUtils.EMPTY;
    
    private List<String> arguments = new ArrayList<String>();

    private SQLiteWhereQueryBuilder() {
    }
    
    public static SQLiteWhereQueryBuilder start() {
        return new SQLiteWhereQueryBuilder();
    }
    
    public static SQLiteWhereQueryBuilder start(String column, String operator, Object operand) {
        return start().add(column, operator, operand);
    }
    
    public SQLiteWhereQueryBuilder add(String column, String operator, Object operand) {
        query += (query.length() != 0 ? " AND " : "") + column + " " + operator + (operand == null ? null : "?");

        if (operand != null) {
            String operandValue = toString(operand);
            arguments.add(operandValue);
        }
        
        return this;
    }
    
    public String get() {
        return query;
    }
    
    public String[] getArguments() {
        return arguments.toArray(new String[arguments.size()]);
    }

    protected String toString(Object value) {
        if (value == null) {
            return null;
        }

        Class<?> propertyType = value.getClass();
        
        if (byte.class.isAssignableFrom(propertyType) || Byte.class.isAssignableFrom(propertyType)) {
            return Byte.toString((Byte) value);
        }
        else if (short.class.isAssignableFrom(propertyType) || Short.class.isAssignableFrom(propertyType)) {
            return String.valueOf((Short) value);
        }
        else if (int.class.isAssignableFrom(propertyType) || Integer.class.isAssignableFrom(propertyType)) {
            return String.valueOf((Integer) value);
        }
        else if (long.class.isAssignableFrom(propertyType) || Long.class.isAssignableFrom(propertyType)) {
            return String.valueOf((Long) value);
        }
        else if (float.class.isAssignableFrom(propertyType) || Float.class.isAssignableFrom(propertyType)) {
            return String.valueOf((Float) value);
        }
        else if (double.class.isAssignableFrom(propertyType) || Double.class.isAssignableFrom(propertyType)) {
            return String.valueOf((Double) value);
        }
        else if (boolean.class.isAssignableFrom(propertyType) || Boolean.class.isAssignableFrom(propertyType)) {
            return ((Boolean) value) ? "1" : "0";
        }
        else if (char.class.isAssignableFrom(propertyType) || Character.class.isAssignableFrom(propertyType)
                || String.class.isAssignableFrom(propertyType)) {
            return value.toString();
        }
        else if (propertyType.isEnum()) {
            return ((Enum<?>) value).name();
        }
        else if (Collection.class.isAssignableFrom(propertyType)) {
            // Support for String collections
            return StringUtils.join((Collection<?>) value, ",");
        }
        else {
            throw new IllegalArgumentException(String.format("Unsupported property type %s.", propertyType));
        }
    }
    
    public static final class Operators {

        public static final String EQ = "=";
        public static final String NEQ = "!=";
        public static final String GT = ">";
        public static final String LT = "<";
        public static final String GTEQ = ">=";
        public static final String LTEQ = "<=";
        public static final String LIKE = "LIKE";
        public static final String IS = "IS";
        public static final String ISNOT = "IS NOT";
        public static final String REGEXP = "REGEXP";
    }
}
